import librosa
import os
from sklearn.cluster import KMeans
import numpy as np
from sklearn.metrics import pairwise_distances


def extract_f0_from_audio(file_path):
    y, sr = librosa.load(file_path, sr=None)
    f0, voiced_flag, _ = librosa.pyin(y, fmin=librosa.note_to_hz('C2'), fmax=librosa.note_to_hz('C7'))
    return f0[voiced_flag]  # 只保留有声部分的基本频率
def extract_all_f0(directory):
    all_f0 = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith(".mp3"):  # 或其他音频格式
                audio_file = os.path.join(root, file)
                f0 = extract_f0_from_audio(audio_file).reshape(-1, 1)
                all_f0.extend(f0)
    return all_f0
def perform_kmeans_clustering(data, n_clusters=3):
    kmeans = KMeans(n_clusters=n_clusters)
    kmeans.fit(np.array(data).reshape(-1, 1))
    return kmeans.labels_, kmeans.cluster_centers_
directory = r"E:\dogbarkdata\AudioClassification\dataset\dogbarking\audio\fold0"
all_f0 = extract_all_f0(directory)
# 定义类间质心距离之和

def dbetw(kmeans):

    centroids = kmeans.cluster_centers_

    n_clusters = centroids.shape[0]

    total_inertia = kmeans.inertia_

    inter_cluster_distances = pairwise_distances(centroids, metric='euclidean')

    dbetw = np.sum(inter_cluster_distances) / (n_clusters * (n_clusters - 1))

    return dbetw


# 定义类内距离之和

def dwith(kmeans):

    return kmeans.inertia_


# 定义聚类有效性评价函数 f(k)

def f(kmeans):

    return abs(np.sqrt(dbetw(kmeans) / dwith(kmeans))-1)


# 穷举不同的聚类数量

k_values = range(1, 51)

f_values = []


for k in k_values:

    kmeans = KMeans(n_clusters=k, random_state=42).fit(all_f0)

    f_value = f(kmeans)

    print(k,f_value)




